package com.irdstudio.efp.esb.api.rest.sed.credit;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.irdstudio.basic.framework.core.constant.EsbRetCodeStandard;
import com.irdstudio.basic.framework.core.constant.SDicToExternalConstant;
import com.irdstudio.basic.framework.core.exception.BizException;
import com.irdstudio.basic.framework.core.util.StringUtil;
import com.irdstudio.basic.framework.core.util.TraceUtil;
import com.irdstudio.basic.framework.core.util.sdic.SDicToExternal;
import com.irdstudio.efp.esb.api.bean.sed.credit.req.ReqPersonalQuotaInfoQurBean;
import com.irdstudio.efp.esb.api.bean.sed.credit.resp.LmtInfArry;
import com.irdstudio.efp.esb.api.bean.sed.credit.resp.RespPersonalQuptaInfoBean;
import com.irdstudio.efp.esb.api.common.EsbRespServiceBeanCreator;
import com.irdstudio.efp.esb.api.common.sed.PersonalQuoatQueryType;
import com.irdstudio.efp.esb.common.constant.EsbBizEnums;
import com.irdstudio.efp.esb.common.constant.EsbSysHeadEnums;
import com.irdstudio.efp.esb.common.server.req.EsbReqServiceBean;
import com.irdstudio.efp.esb.common.server.resp.EsbRespServiceBean;
import com.irdstudio.efp.limit.service.facade.LmtPrdContService;
import com.irdstudio.efp.limit.service.vo.LmtPrdContVO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
* 普税贷产品对税e贷产品的此部分代码做了复用
* 说明：为了保证功能的复用性、提升开发的工作效率，对该代码进行了复用
* 评估是否会影响线上功能：否
* 评估时间：2020/5/25
* 处理方案：保留复用
*/
/**
 * 
 * 个人额度查询
 * @author wanglihua
 * @since 2019年4月23日 下午7:50:35
 * @version 1.0
 */
@RestController
@RequestMapping("/esb")
public class PersonalQuotaInfoQusController {

	private static Logger logger = LoggerFactory.getLogger(PersonalQuotaInfoQusController.class);

	@Autowired
	@Qualifier("lmtPrdContService")
	private LmtPrdContService lmtPrdContService;

	@ModelAttribute("esbReqServiceBean")
	public EsbReqServiceBean getReqEsbHeadBean(HttpServletRequest request) {
		logger.info("获取ESB请求对象，校验 ESB请求系统头和请求应用头对象开始");
		EsbReqServiceBean esbReqServiceBean = (EsbReqServiceBean) request.getAttribute("esbReqServiceBean");
		return esbReqServiceBean;
	}

	@ModelAttribute("reqBean")
	public ReqPersonalQuotaInfoQurBean getReqEsbBodyBean(HttpServletRequest request) {
		logger.info("获取个人额度查询接口请求对象，校验合同要素查询接口请求体对象开始");
		String esbReqBody = (String) request.getAttribute("esbReqBody");
		return JSONObject.parseObject(esbReqBody, ReqPersonalQuotaInfoQurBean.class);
	}

	@PostMapping("/SERVICE_30230003_02")
	public EsbRespServiceBean doRecv(@Validated @ModelAttribute("esbReqServiceBean") EsbReqServiceBean esbReqServiceBean, BindingResult br1,
                                     @Validated @ModelAttribute("reqBean") ReqPersonalQuotaInfoQurBean reqBean, BindingResult br2, Exception exception) throws Exception {
		String queryType = reqBean.getQryTp();
		String globalSerno = esbReqServiceBean.getSysHead().getGlblSrlNo();
		TraceUtil.setTraceId(globalSerno);
		logger.info("*********个人额度查询接口处理开始，查询类型为：" + PersonalQuoatQueryType.getValue(queryType) + "*********");
		List<LmtPrdContVO> totalResult = new ArrayList<LmtPrdContVO>();
		List<LmtPrdContVO> result = new ArrayList<LmtPrdContVO>();
		try {
			// 通过切面校验个人用信申请查询请求参数是否正确，如不正确则返回错误信息
			if (Objects.nonNull(exception)) {
				throw exception;
			}
			//查询结果
			totalResult = execQuery(reqBean);
			//排序--按时间降序
			if (totalResult != null && totalResult.size() > 1) {
				totalResult.sort((o1, o2) -> {
					LocalDateTime createTime2 = LocalDateTime.parse(o2.getCreateTime(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
					LocalDateTime createTime1 = LocalDateTime.parse(o1.getCreateTime(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
					long l2 = Instant.from(createTime2.atZone(ZoneId.systemDefault())).toEpochMilli();
					long l1 = Instant.from(createTime1.atZone(ZoneId.systemDefault())).toEpochMilli();
					return Long.compare(l2, l1);
				});
			}
			//分割结果
			result = groupTotalResult(totalResult,reqBean);
			RespPersonalQuptaInfoBean respPersonalQuptaInfoBean = buildRespPersonalQuptaInfoBean(result, reqBean);
			respPersonalQuptaInfoBean.setCrrspnQryTotCnt(String.valueOf(totalResult.size()));
			return EsbRespServiceBeanCreator.buildesbRespServiceBean(esbReqServiceBean,
					JSON.toJSONString(respPersonalQuptaInfoBean),
					EsbSysHeadEnums.RetStEnum.SUCCESS.getCode(),
					EsbBizEnums.RetCodeEnum.SUCCESS.getVALUE(),
					"查询成功");
		} catch (BizException e) {
			return EsbRespServiceBeanCreator.buildesbRespServiceBean(esbReqServiceBean,
					JSON.toJSONString(buildRespPersonalQuptaInfoBean(result,reqBean)),
					EsbSysHeadEnums.RetStEnum.FAILURE.getCode(),
					EsbRetCodeStandard.JKYDCSJYBTG.getValue(),
					e.getMessage());
		} catch (Exception e) {
			logger.error("***********调用个人额度信息查询接口处理失败"+e.getMessage()+"**************");
			return EsbRespServiceBeanCreator.buildesbRespServiceBean(esbReqServiceBean,
					JSON.toJSONString(buildRespPersonalQuptaInfoBean(result,reqBean)),
					EsbSysHeadEnums.RetStEnum.FAILURE.getCode(),
					EsbRetCodeStandard.OTHERS_EXCEPTION.getValue(),
					e.getMessage());
		} finally {
			logger.error("***********调用个人额度信息查询接口处理结束**************");
			TraceUtil.clear();
		}
	}

	private List<LmtPrdContVO> groupTotalResult(List<LmtPrdContVO> totalResult, ReqPersonalQuotaInfoQurBean reqBean) {
		if(StringUtil.isNullorBank(reqBean.getPgNo())) {
			reqBean.setPgNo("1");
		}
		if(StringUtil.isNullorBank(reqBean.getPerPgRcrNum())) {
			reqBean.setPerPgRcrNum("10");
		}
		String pageNo = reqBean.getPgNo();
		String pageSize = reqBean.getPerPgRcrNum();

		int limit = totalResult.size() / Integer.parseInt(pageSize) + 1;
		int num = Integer.parseInt(pageNo) - 1;
		List<List<LmtPrdContVO>> spiltList = Stream.iterate(0, n -> n + 1)
				.limit(limit)
				.parallel()
				.map(a -> totalResult.stream()
						.skip(a * Integer.parseInt(pageSize))
						.limit(Integer.parseInt(pageSize))
						.parallel()
						.collect(Collectors.toList()))
				.collect(Collectors.toList());
		return spiltList.get(num);
	}

	private List<LmtPrdContVO> execQuery(ReqPersonalQuotaInfoQurBean reqBean) throws Exception {
		String queryType = reqBean.getQryTp();
		String lmtApplySeq = reqBean.getCrdtAppFlowNo();
		String certCode = reqBean.getCertNo();
		String certType = reqBean.getCertTp();
		String prdId = reqBean.getPrdctID();
		String channelNo = reqBean.getChanNo();
		String lmtStatus = reqBean.getBtchLmtStCd();
		String cusId = reqBean.getClntNo();

		LmtPrdContVO lmtPrdContVO = new LmtPrdContVO();
		lmtPrdContVO.setCertType(certType);
		lmtPrdContVO.setCertCode(certCode);
		lmtPrdContVO.setLmtApplySeq(lmtApplySeq);
		lmtPrdContVO.setPrdId(prdId);
		lmtPrdContVO.setChannelNo(channelNo);
		lmtPrdContVO.setLmtStatus(lmtStatus);
		lmtPrdContVO.setCusId(cusId);

		List<LmtPrdContVO> result = new ArrayList<LmtPrdContVO>();
		// 01 单笔个人额度信息查询 
		if(PersonalQuoatQueryType.ONE_QUOTA.getKey().equals(queryType)) {
			logger.info("*********查询类型：" + PersonalQuoatQueryType.ONE_QUOTA.getValue() + "*********");
			if(StringUtil.isNullorBank(lmtApplySeq)) {
				throw new Exception(PersonalQuoatQueryType.getValue(queryType) + "需要上送授信申请流水号!");
			}
			lmtPrdContVO = lmtPrdContService.queryOneQuota(lmtPrdContVO);
			if(Objects.nonNull(lmtPrdContVO)) {
				result.add(lmtPrdContVO);
			}
		} else {
			if(StringUtil.isNullorBank(certCode)) {
				throw new BizException(PersonalQuoatQueryType.getValue(queryType) + "未上送证件号！");
			}
			if(StringUtil.isNullorBank(certType)) {
				throw new BizException(PersonalQuoatQueryType.getValue(queryType) + "未上送证件类型！");
			}
			// 02 单客户下所有的个人额度信息查询 
			if(PersonalQuoatQueryType.ONE_CUS_ALL.getKey().equals(queryType)) {
				logger.info("*********查询类型：" + PersonalQuoatQueryType.ONE_CUS_ALL.getValue() + "*********");
				result = lmtPrdContService.queryOneCus(lmtPrdContVO);
				// 03 单笔客户下某个产品下个人额度信息查询 
			} else if(PersonalQuoatQueryType.ONE_CUS_PRD_ONE.getKey().equals(queryType)) {
				logger.info("*********查询类型：" + PersonalQuoatQueryType.ONE_CUS_PRD_ONE.getValue() + "*********");
				if(StringUtil.isNullorBank(prdId)) {
					throw new BizException(PersonalQuoatQueryType.getValue(queryType) + "未上送产品ID！");
				}
				result = lmtPrdContService.queryOneCus(lmtPrdContVO);
				// 04 单笔客户下某个渠道下个人额度信息
			} else if(PersonalQuoatQueryType.ONE_CUS_CHANNEL_ALL.getKey().equals(queryType)) {
				logger.info("*********查询类型：" + PersonalQuoatQueryType.ONE_CUS_CHANNEL_ALL.getValue() + "*********");
				if(StringUtil.isNullorBank(channelNo)) {
					throw new BizException(PersonalQuoatQueryType.getValue(queryType) + "未上送渠道号！");
				}
				result = lmtPrdContService.queryOneCus(lmtPrdContVO);
				// 05 单笔客户下某个额度状态为待生效、生效、失效、签订中 的个人额度信息-证件类型、证件号码、审批状态必输
			} else if(PersonalQuoatQueryType.ONE_CUS_APPR_ALL.getKey().equals(queryType)) {
				logger.info("*********查询类型：" + PersonalQuoatQueryType.ONE_CUS_APPR_ALL.getValue() + "*********");
				if(StringUtil.isNullorBank(lmtStatus)) {
					throw new BizException(PersonalQuoatQueryType.getValue(queryType) + "未上送审批状态！");
				}
				result = lmtPrdContService.queryOneCus(lmtPrdContVO);
				//06 单个客户下查询所有处理中、通过、拒绝的人额度信息-证件类型、证件号码、产品ID、审批状态必输
			} else if(PersonalQuoatQueryType.ONE_CUS_APPR_ALL_PRDID.getKey().equals(queryType)) {
				logger.info("*********查询类型：" + PersonalQuoatQueryType.ONE_CUS_APPR_ALL_PRDID.getValue() + "*********");
				if(StringUtil.isNullorBank(lmtStatus)) {
					throw new BizException(PersonalQuoatQueryType.getValue(queryType) + "未上送审批状态！");
				}
				if(StringUtil.isNullorBank(prdId)) {
					throw new BizException(PersonalQuoatQueryType.getValue(queryType) + "未上送产品ID！");
				}
				result = lmtPrdContService.queryOneCus(lmtPrdContVO);
			}
		}
		return result;
	}

	@SuppressWarnings({ "unlikely-arg-type", "null" })
	private static RespPersonalQuptaInfoBean buildRespPersonalQuptaInfoBean(List<LmtPrdContVO> result, ReqPersonalQuotaInfoQurBean reqBean) throws Exception {
		RespPersonalQuptaInfoBean respBean = new RespPersonalQuptaInfoBean();
		logger.info("***********开始组装返回报文Body。***********");
		respBean.setPgNo(reqBean.getPgNo());
		respBean.setPerPgRcrNum(reqBean.getPerPgRcrNum());
		respBean.setCertNo(reqBean.getCertNo());//证件号码
		respBean.setCertTp(reqBean.getCertTp());//证件类型
		respBean.setClntNo(reqBean.getClntNo());//客户编号
		if(result == null || result.isEmpty() || "[]".equals(result)) {
			respBean.setCrrspnQryTotCnt("0");
		} else {
			respBean.setCertNo(result.get(0).getCertCode());//证件号码
			respBean.setCertTp(result.get(0).getCertType());//证件类型
			respBean.setClntNo(result.get(0).getCusId());//客户编号
			respBean.setCustNm(result.get(0).getCusName());//客户名称
			respBean.setCrrspnQryTotCnt(String.valueOf(result.size()));

			List<LmtInfArry> tempList = new ArrayList<LmtInfArry>();
			Iterator<LmtPrdContVO> iterator = result.iterator();
			while(iterator.hasNext()){
				LmtPrdContVO tempEle = iterator.next();
				LmtInfArry respLmtInfArry = new LmtInfArry();
				respLmtInfArry.setCrdtContrNo(tempEle.getLmtContNo()); //授信协议编号
				respLmtInfArry.setCrdtAppFlowNo(tempEle.getLmtApplySeq());//授信申请流水号
				respLmtInfArry.setChanNo(tempEle.getChannelNo());//渠道号
				respLmtInfArry.setPrdctID(tempEle.getPrdId());//产品id
				respLmtInfArry.setLoanProdNm(tempEle.getPrdName());//产品名称
				respLmtInfArry.setCrdtLmt(tempEle.getLmtAmt()==null?"":tempEle.getLmtAmt().toString());//授信额度
				respLmtInfArry.setAvlLmt(tempEle.getAvailAmt()==null?"":tempEle.getAvailAmt().toString());//可用额度
				respLmtInfArry.setTkpLmt(tempEle.getPreOccAmt()==null?"":tempEle.getPreOccAmt().toString());//预占用额度
				respLmtInfArry.setUsedLmt(tempEle.getOccAmt()==null?"":tempEle.getOccAmt().toString());//已用额度
				respLmtInfArry.setRvlvFlg(tempEle.getCyclicFlg());//是否循环
				respLmtInfArry.setTxnCurrCd(SDicToExternal.getExternalSysDicVal(SDicToExternalConstant.SYSID_IFP, SDicToExternalConstant.CUR_TYPE,tempEle.getCurrencyType()));//币种
				respLmtInfArry.setLoanAplTrm(tempEle.getTerm()==null?"":tempEle.getTerm().toString());//期限
				respLmtInfArry.setLoanTrmType(SDicToExternal.getExternalSysDicVal(SDicToExternalConstant.SYSID_IFP, SDicToExternalConstant.TERM_TYPE,tempEle.getTermType()));//期限类型
				respLmtInfArry.setLoanRate(tempEle.getRateY()==null?"0":tempEle.getRateY().toString());//利率(年)
				respLmtInfArry.setGuarMd(SDicToExternal.getExternalSysDicVal(SDicToExternalConstant.SYSID_IFP, SDicToExternalConstant.Assure_Means_Main,tempEle.getAssureMeansMain()));//担保方式
				respLmtInfArry.setRpyMd(SDicToExternal.getExternalSysDicVal(SDicToExternalConstant.SYSID_IFP, SDicToExternalConstant.REPAY_MODE,tempEle.getRepaymentMode()));//还款方式
				respLmtInfArry.setRpyCyc(tempEle.getRepaymentPeriod()==null?"":tempEle.getRepaymentPeriod().toString());//还款周期
				respLmtInfArry.setRpyCycCorpCd(SDicToExternal.getExternalSysDicVal(SDicToExternalConstant.SYSID_IFP, SDicToExternalConstant.TERM_TYPE,tempEle.getRepaymentPeriodType()));//还款周期单位
				respLmtInfArry.setRpyDtTp(tempEle.getRepaymentDayType());//还款日类型
				respLmtInfArry.setRpyDt(tempEle.getRepaymentDay()==null?"":tempEle.getRepaymentDay().toString());//还款日
				respLmtInfArry.setLoanUsg(tempEle.getLoanUse());//贷款用途
				respLmtInfArry.setLmtSt(tempEle.getLmtStatus());//额度状态
				respLmtInfArry.setStrtDt(tempEle.getStartDate());//起始日
				respLmtInfArry.setMateDt(tempEle.getExpireDate());//到期日期
				respLmtInfArry.setSgnDt(tempEle.getSignDate());//签订日期
				respLmtInfArry.setCrdtDt(tempEle.getValidDays()==null?"":tempEle.getValidDays().toString());//授信批复有效期
				respLmtInfArry.setClntMgrNo(tempEle.getCusManager());//客户经理
				respLmtInfArry.setMgtOrgId(tempEle.getMainBrId());//管理机构
				respLmtInfArry.setFrzFlowNo(tempEle.getFrzSerno());//冻结流水号
				respLmtInfArry.setDistrCardNo(tempEle.getLoanAccount());//放款账户
				respLmtInfArry.setBankCardNo(tempEle.getRecvAccount());//还款账户
				tempList.add(respLmtInfArry);
			}
			respBean.setLmtInfArry(tempList);
		}
		logger.info("***********组装结束。***********");
		return respBean;
	}
}
